package commands

import (
	"errors"
	"strconv"
	"strings"
	"time"

	"github.com/larspensjo/config"
	"github.com/urfave/cli"

	"../flags"
	"../utils"
)

// Apply - apply publish
func Apply(config utils.Config) cli.Command {
	return cli.Command{
		Name:     "apply",
		Usage:    "apply publish",
		Category: "MANAGER COMMANDS",
		Flags: []cli.Flag{
			flags.Flags["path"],
		},
		Action: makeAction(config, applyAction),
	}
}

/*
## master
# 审查并通过 hotfixes/release 分支的合并请求【小/中版本升级】
sgbm-cli apply

## manager
# 审查并通过 feature 分支的合并请求
sgbm-cli apply
*/

func applyAction(conf utils.Config, git utils.Git, context *cli.Context) error {
	configResult, err := utils.LoadConfig(conf, git, "config")
	if err != nil {
		return err
	}
	var ownName, ownRole string
	ownName, err = configResult.String("session", conf.PcCode)
	if err != nil {
		return errors.New("Please login")
	}
	ownRole, err = configResult.String("user", ownName)
	if err != nil {
		return errors.New("Session Info Error")
	}
	if ("master" != ownRole) && ("manager" != ownRole) {
		return errors.New("Please login with master/manager")
	}

	var masterName, devName, head string
	masterName, err = configResult.String("global", "master")
	if err != nil {
		return err
	}
	devName, err = configResult.String("global", "dev")
	if err != nil {
		return err
	}
	head, err = git.ThisBranch()
	if err != nil {
		return err
	}

	if (head == masterName) || (head == devName) {
		return errors.New("Apply can't be used in master/dev branch")
	}

	temp := strings.Split(head, "--")
	TYPE := temp[0]
	ID := temp[1]

	if "feature" == TYPE {
		_, err = git.Execute(
			[]string{"pull", "--all"},
			[]string{"checkout", devName},
			[]string{"merge", "--no-ff", head},
			[]string{"branch", "-d", head},
			[]string{"branch", "-r", "-d", "origin/" + head},
			[]string{"push", "-u", "origin", "--all"},
		)
		if err != nil {
			return err
		}

		return utils.AddConfig(conf, git, "log", func(c *config.Config) *config.Config {
			TASK := "task-" + ID
			c.AddOption(TASK, "active", "false")
			return c
		})
	}

	if "manager" == ownRole {
		return errors.New("Please login with master")
	}

	if "hotfixes" == TYPE {
		var ver string
		ver, err = configResult.String("global", "ver")
		if err != nil {
			return err
		}
		ver, err = utils.UpdateVersionSmall(ver)
		if err != nil {
			return err
		}
		err = utils.AddConfig(conf, git, "config", func(c *config.Config) *config.Config {
			c.AddOption("global", "ver", ver)
			return c
		})
		if err != nil {
			return err
		}

		_, err = git.Execute(
			[]string{"pull", "--all"},
			[]string{"checkout", devName},
			[]string{"merge", "--no-ff", head},
			[]string{"checkout", masterName},
			[]string{"merge", "--no-ff", head},
			[]string{"tag", "v" + ver + "-RELEASE"},
			[]string{"branch", "-d", head},
			[]string{"branch", "-r", "-d", "origin/" + head},
			[]string{"push", "-u", "origin", "--all"},
			[]string{"push", "-u", "origin", "--tags"},
		)
		if err != nil {
			return err
		}

		return utils.AddConfig(conf, git, "log", func(c *config.Config) *config.Config {
			TASK := "task-" + ID
			c.AddOption(TASK, "active", "false")
			return c
		})
	}

	if "release" == TYPE {
		var ver string
		ver, err = configResult.String("global", "ver")
		if err != nil {
			return err
		}
		ver, err = utils.UpdateVersionMiddle(ver)
		if err != nil {
			return err
		}
		err = utils.AddConfig(conf, git, "config", func(c *config.Config) *config.Config {
			c.AddOption("global", "ver", ver)
			return c
		})
		if err != nil {
			return err
		}

		_, err = git.Execute(
			[]string{"pull", "--all"},
			[]string{"checkout", devName},
			[]string{"merge", "--no-ff", head},
			[]string{"checkout", masterName},
			[]string{"merge", "--no-ff", head},
			[]string{"tag", "v" + ver + "-RELEASE"},
			[]string{"branch", "-d", head},
			[]string{"branch", "-r", "-d", "origin/" + head},
			[]string{"push", "-u", "origin", "--all"},
			[]string{"push", "-u", "origin", "--tags"},
		)
		if err != nil {
			return err
		}

		time := time.Now().Unix()
		TIME := strconv.FormatInt(time, 10)
		return utils.AddConfig(conf, git, "log", func(c *config.Config) *config.Config {
			TASK := "task-" + ID
			c.AddOption(TASK, "active", "false")
			c.AddOption(TASK, "finish_user", ownName)
			c.AddOption(TASK, "finish_time", TIME)
			return c
		})
	}

	return errors.New("Task Type Error")
}
